﻿using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Windows;

namespace datatool
{
    public class dataItem
    {
        public byte M1 { get; set; }
        public byte M2 { get; set; }
        public byte M3 { get; set; }
        public byte M4 { get; set; }
        public byte M5 { get; set; }
        public byte M6 { get; set; }
        public byte M7 { get; set; }
        public byte M8 { get; set; }
        public byte M9 { get; set; }
        public byte M10 { get; set; }
        public byte M11 { get; set; }
        public byte M12 { get; set; }
        public byte M13 { get; set; }
        public byte M14 { get; set; }
        public byte M15 { get; set; }
        public byte M16 { get; set; }
        public byte M17 { get; set; }
        public byte M18 { get; set; }
        public byte M19 { get; set; }
        public byte M20 { get; set; }
        public byte M21 { get; set; }
        public byte M22 { get; set; }
        public byte M23 { get; set; }
        public byte M24 { get; set; }
        public byte M25 { get; set; }
        public byte M26 { get; set; }
        public byte M27 { get; set; }
        public byte M28 { get; set; }
        public byte M29 { get; set; }
        public byte M30 { get; set; }
        public byte M31 { get; set; }
        public byte M32 { get; set; }
        public byte M33 { get; set; }
        public byte M34 { get; set; }
        public byte M35 { get; set; }
        public byte M36 { get; set; }
        public byte M37 { get; set; }
        public byte M38 { get; set; }
        public byte M39 { get; set; }
        public byte M40 { get; set; }
        public byte M41 { get; set; }
        public byte M42 { get; set; }
        public byte M43 { get; set; }
        public byte M44 { get; set; }
        public byte M45 { get; set; }
        public byte M46 { get; set; }
        public byte M47 { get; set; }
        public byte M48 { get; set; }
        public byte M49 { get; set; }
        public byte M50 { get; set; }
        public byte M51 { get; set; }
        public byte M52 { get; set; }
        public byte M53 { get; set; }
        public byte M54 { get; set; }
        public byte M55 { get; set; }
        public byte M56 { get; set; }
        public byte M57 { get; set; }
        public byte M58 { get; set; }
        public byte M59 { get; set; }
        public byte M60 { get; set; }
        public byte M61 { get; set; }
        public byte M62 { get; set; }
        public byte M63 { get; set; }
        public byte M64 { get; set; }
        public byte M65 { get; set; }
        public byte M66 { get; set; }
        public byte M67 { get; set; }
        public byte M68 { get; set; }
        public byte M69 { get; set; }
        public byte M70 { get; set; }
        public byte M71 { get; set; }
        public byte M72 { get; set; }
        public byte M73 { get; set; }
        public byte M74 { get; set; }
        public byte M75 { get; set; }
        public byte M76 { get; set; }
        public byte M77 { get; set; }
        public byte M78 { get; set; }
        public byte M79 { get; set; }
        public byte M80 { get; set; }

        public dataItem(byte[] buf, int offset)
        {
            M1 = buf[offset];
            M2 = buf[offset + 1];
            M3 = buf[offset + 2];
            M4 = buf[offset + 3];
            M5 = buf[offset + 4];
            M6 = buf[offset + 5];
            M7 = buf[offset + 6];
            M8 = buf[offset + 7];
            M9 = buf[offset + 8];
            M10 = buf[offset + 9];
            M11 = buf[offset + 10];
            M12 = buf[offset + 11];
            M13 = buf[offset + 12];
            M14 = buf[offset + 13];
            M15 = buf[offset + 14];
            M16 = buf[offset + 15];
            M17 = buf[offset + 16];
            M18 = buf[offset + 17];
            M19 = buf[offset + 18];
            M20 = buf[offset + 19];
            M21 = buf[offset + 20];
            M22 = buf[offset + 21];
            M23 = buf[offset + 22];
            M24 = buf[offset + 23];
            M25 = buf[offset + 24];
            M26 = buf[offset + 25];
            M27 = buf[offset + 26];
            M28 = buf[offset + 27];
            M29 = buf[offset + 28];
            M30 = buf[offset + 29];
            M31 = buf[offset + 30];
            M32 = buf[offset + 31];
            M33 = buf[offset + 32];
            M34 = buf[offset + 33];
            M35 = buf[offset + 34];
            M36 = buf[offset + 35];
            M37 = buf[offset + 36];
            M38 = buf[offset + 37];
            M39 = buf[offset + 38];
            M40 = buf[offset + 39];
            M41 = buf[offset + 40];
            M42 = buf[offset + 41];
            M43 = buf[offset + 42];
            M44 = buf[offset + 43];
            M45 = buf[offset + 44];
            M46 = buf[offset + 45];
            M47 = buf[offset + 46];
            M48 = buf[offset + 47];
            M49 = buf[offset + 48];
            M50 = buf[offset + 49];
            M51 = buf[offset + 50];
            M52 = buf[offset + 51];
            M53 = buf[offset + 52];
            M54 = buf[offset + 53];
            M55 = buf[offset + 54];
            M56 = buf[offset + 55];
            M57 = buf[offset + 56];
            M58 = buf[offset + 57];
            M59 = buf[offset + 58];
            M60 = buf[offset + 59];
            M61 = buf[offset + 60];
            M62 = buf[offset + 61];
            M63 = buf[offset + 62];
            M64 = buf[offset + 63];
            M65 = buf[offset + 64];
            M66 = buf[offset + 65];
            M67 = buf[offset + 66];
            M68 = buf[offset + 67];
            M69 = buf[offset + 68];
            M70 = buf[offset + 69];
            M71 = buf[offset + 70];
            M72 = buf[offset + 71];
            M73 = buf[offset + 72];
            M74 = buf[offset + 73];
            M75 = buf[offset + 74];
            M76 = buf[offset + 75];
            M77 = buf[offset + 76];
            M78 = buf[offset + 77];
            M79 = buf[offset + 78];
            M80 = buf[offset + 79];
        }

        public byte[] GetBuff()
        {
            byte[] bytes = new byte[80];
            bytes[0] = M1;
            bytes[1] = M2;
            bytes[2] = M3;
            bytes[3] = M4;
            bytes[4] = M5;
            bytes[5] = M6;
            bytes[6] = M7;
            bytes[7] = M8;
            bytes[8] = M9;
            bytes[9] = M10;
            bytes[10] = M11;
            bytes[11] = M12;
            bytes[12] = M13;
            bytes[13] = M14;
            bytes[14] = M15;
            bytes[15] = M16;
            bytes[16] = M17;
            bytes[17] = M18;
            bytes[18] = M19;
            bytes[19] = M20;
            bytes[20] = M21;
            bytes[21] = M22;
            bytes[22] = M23;
            bytes[23] = M24;
            bytes[24] = M25;
            bytes[25] = M26;
            bytes[26] = M27;
            bytes[27] = M28;
            bytes[28] = M29;
            bytes[29] = M30;
            bytes[30] = M31;
            bytes[31] = M32;
            bytes[32] = M33;
            bytes[33] = M34;
            bytes[34] = M35;
            bytes[35] = M36;
            bytes[36] = M37;
            bytes[37] = M38;
            bytes[38] = M39;
            bytes[39] = M40;
            bytes[40] = M41;
            bytes[41] = M42;
            bytes[42] = M43;
            bytes[43] = M44;
            bytes[44] = M45;
            bytes[45] = M46;
            bytes[46] = M47;
            bytes[47] = M48;
            bytes[48] = M49;
            bytes[49] = M50;
            bytes[50] = M51;
            bytes[51] = M52;
            bytes[52] = M53;
            bytes[53] = M54;
            bytes[54] = M55;
            bytes[55] = M56;
            bytes[56] = M57;
            bytes[57] = M58;
            bytes[58] = M59;
            bytes[59] = M60;
            bytes[60] = M61;
            bytes[61] = M62;
            bytes[62] = M63;
            bytes[63] = M64;
            bytes[64] = M65;
            bytes[65] = M66;
            bytes[66] = M67;
            bytes[67] = M68;
            bytes[68] = M69;
            bytes[69] = M70;
            bytes[70] = M71;
            bytes[71] = M72;
            bytes[72] = M73;
            bytes[73] = M74;
            bytes[74] = M75;
            bytes[75] = M76;
            bytes[76] = M77;
            bytes[77] = M78;
            bytes[78] = M79;
            bytes[79] = M80;

            return bytes;
        }
    }

    public class cmbItem
    {
        public string name { get; set; }
        public byte val { get; set; }
    }

    public class BinaryEditorViewModel : ViewModelBase
    {
        private const int GroupSize = 80;

        private ObservableCollection<dataItem> _BinDatas;

        public ObservableCollection<dataItem> BinDatas
        {
            get { return _BinDatas; }
            set { _BinDatas = value; RaisePropertyChanged(() => BinDatas); }
        }

        private ObservableCollection<cmbItem> _CmbItems;

        public ObservableCollection<cmbItem> CmbItems
        {
            get { return _CmbItems; }
            set { _CmbItems = value; RaisePropertyChanged(() => CmbItems); }
        }


        private int _selItem;

        public int SelItem
        {
            get { return _selItem; }
            set { _selItem = value; RaisePropertyChanged(() => SelItem); }
        }


        public ObservableCollection<ByteData> CurrentGroupBytes { get; } = new ObservableCollection<ByteData>();
        public RelayCommand OpenFileCommand { get; }
        public RelayCommand SaveFileCommand { get; }
        public RelayCommand AddGroupCommand { get; }
        public RelayCommand RemoveGroupCommand { get; }


        public BinaryEditorViewModel()
        {
            CmbItems = [];
            for (int i = 0; i < 0x40; i++)
            {
                CmbItems.Add(new cmbItem { name = string.Format("0x{0:X02}", i), val = (byte)i });
            }

            BinDatas = [];

            OpenFileCommand = new RelayCommand(OpenFile);
            SaveFileCommand = new RelayCommand(SaveFile);
            AddGroupCommand = new RelayCommand(AddGroup);
            RemoveGroupCommand = new RelayCommand(RemoveGroup);

        }

        private void OpenFile()
        {
            var dialog = new OpenFileDialog { Filter = "二进制文件|*.bin|所有文件|*.*" };
            if (dialog.ShowDialog() == true)
            {
                try
                {
                    var fileBytes = File.ReadAllBytes(dialog.FileName);
                    BinDatas = SplitIntoGroupsSrc(fileBytes);
                }
                catch (Exception ex)
                {
                    MessageBox.Show($"打开文件失败: {ex.Message}");
                }
            }
        }

        private ObservableCollection<dataItem> SplitIntoGroupsSrc(byte[] data)
        {
            var groups = new ObservableCollection<dataItem>();
            for (int i = 0; i < data.Length; i += GroupSize)
            {
                if((data.Length - i) < GroupSize)
                {
                    break;
                }
                var group = new dataItem(data, i);
                groups.Add(group);
            }
            return groups;
        }

        private void SaveFile()
        {
            if (BinDatas.Count == 0) return;

            var dialog = new SaveFileDialog { Filter = "二进制文件|*.bin|所有文件|*.*" };
            if (dialog.ShowDialog() == true)
            {
                try
                {
                    using (var stream = new FileStream(dialog.FileName, FileMode.Create))
                    {
                        foreach (var group in BinDatas)
                        {
                            byte[] datas = group.GetBuff();
                            stream.Write(datas, 0, datas.Length);
                        }
                    }
                    MessageBox.Show("保存成功");
                }
                catch (Exception ex)
                {
                    MessageBox.Show($"保存文件失败: {ex.Message}");
                }
            }
        }

        private void AddGroup()
        {
            BinDatas.Add(new dataItem(BinDatas[BinDatas.Count - 1].GetBuff(), 0));
        }

        private void RemoveGroup()
        {
            if(SelItem >= 0 && SelItem < BinDatas.Count)
            {
                var dialog = new ConfirmDialog($"确认删除第{SelItem}组数据？")
                {
                    WindowStartupLocation = WindowStartupLocation.CenterScreen
                };

                if (dialog.ShowDialog() == false)
                {
                    return;
                }

                BinDatas.RemoveAt(SelItem);
            }
        }
    }
}
